﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.Net;
using System.Text.RegularExpressions;

namespace YouTubeScraper
{
    public partial class Scraper : Form
    {
        BackgroundWorker worker = new BackgroundWorker();
        int pages = 1;
        string searchUrl = "http://www.youtube.com/results?search_type=videos&search_query=";
        string searchTerm = "";
        string sortTerm = "";
        bool useSearchTermAsTag = false;
        Dictionary<string, string> Sorting = new Dictionary<string, string>();

        public delegate void VideosAddedHandler(Dictionary<string, string> videos);
        public event VideosAddedHandler VideosAdded;

        enum SortingText
        {
            Relevance,
            UploadDate,
            ViewCount,
            Rating
        }

        public Scraper()
        {
            InitializeComponent();

            Icon = YouTubeStormer.Properties.Resources.configureIcon;

            Sorting.Add(SortingText.Relevance.ToString(), "");
            Sorting.Add(SortingText.UploadDate.ToString(), "&search_sort=video_date_uploaded");
            Sorting.Add(SortingText.ViewCount.ToString(), "&search_sort=video_view_count");
            Sorting.Add(SortingText.Rating.ToString(), "&search_sort=video_avg_rating");

            foreach (KeyValuePair<string, string> sorts in Sorting)
            {
                comboBox1.Items.Add(sorts.Key);
            }
            comboBox1.SelectedItem = SortingText.Relevance.ToString();

            worker.DoWork += worker_DoWork;
            worker.ProgressChanged += worker_ProgressChanged;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;

            FormClosing += new FormClosingEventHandler(Scraper_FormClosing);
        }

        void Scraper_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        class Result
        {
            public string VideoID { get; set; }
            public string Title { get; set; }
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            textBoxSearchTerm.Enabled = true;
            buttonStart.Text = "Scrape";
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var result = e.UserState as Result;
            var row = new DataGridViewRow();
            row.CreateCells(dataGridView1);
            row.Cells[0].Value = result.VideoID;
            row.Cells[1].Value = result.Title;
            dataGridView1.Rows.Add(row);

        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            WebClient webClient = new WebClient();

            for (int i = 1; i <= pages; i++)
            {
                string pageText = webClient.DownloadString(searchUrl + searchTerm + "&page=" + i + sortTerm);
                if (worker.CancellationPending) return;
                var pageLines = pageText.Split('\n');
                for (int p = 0; p < pageLines.Length; p++)
                {
                    if (pageLines[p].Contains("<a id=\"video-long-title-"))
                    {
                        string videoID = Regex.Split(pageLines[p], "<a id=\"video-long-title-")[1].Split('"')[0];
                        string title = HttpUtility.UrlDecode(Regex.Split(Regex.Split(pageLines[p], "title=\"")[1], "\" rel=")[0]);

                        if (!webClient.DownloadString("http://www.youtube.com/watch?v=" + videoID).Contains("comments has been disabled"))
                            worker.ReportProgress(0, new Result { VideoID = videoID, Title = title });

                        if (worker.CancellationPending) return;
                    }
                }

            }
        }

        string buttonStartScrape = "Scrape";
        string buttonStartStop = "Stop";

        private void buttonStart_Click(object sender, EventArgs e)
        {
            if (buttonStart.Text == buttonStartScrape)
                StartScrape();
            else
                StopScrape();
        }

        private void StartScrape()
        {
            textBoxSearchTerm.Enabled = false;
            buttonStart.Text = buttonStartStop;
            sortTerm = Sorting[comboBox1.SelectedItem.ToString()];
            searchTerm = HttpUtility.UrlEncode(textBoxSearchTerm.Text);
            worker.RunWorkerAsync();
        }

        private void StopScrape()
        {
            buttonStart.Text = buttonStartScrape;
            worker.CancelAsync();
        }

        private void numericUpDownPages_ValueChanged(object sender, EventArgs e)
        {
            pages = (int)(sender as NumericUpDown).Value;
        }

        private void buttonCopy_Click(object sender, EventArgs e)
        {
            CopyRowsToClipboard(dataGridView1.SelectedRows);
        }

        private void buttonCopyAll_Click(object sender, EventArgs e)
        {
            CopyRowsToClipboard(dataGridView1.Rows);
        }

        void CopyRowsToClipboard(dynamic rows)
        {
            var VideoInfoEntries = new Dictionary<string, string>();
            VideoInfoEntries.Clear();
            foreach (DataGridViewRow row in rows)
            {
                if (!VideoInfoEntries.ContainsKey(row.Cells[0].Value as string))
                {
                    VideoInfoEntries.Add(row.Cells[0].Value as string, row.Cells[1].Value as string);
                }
            }
            VideosAdded(VideoInfoEntries);
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            dataGridView1.Rows.Clear();
        }

        private void checkBoxUseTitleAsTag_CheckedChanged(object sender, EventArgs e)
        {
            useSearchTermAsTag = checkBoxUseTitleAsTag.Checked;
        }
    }
}
